# -*- coding: utf-8 -*-
"""
异常评分系统 - 10分制评分机制
该模块实现了基于多维度评估的异常严重度评分系统，用于对系统异常进行量化评估
"""

import json
import os
import time
from datetime import datetime, timezone
from dataclasses import dataclass, asdict
from typing import Dict, List, Any, Optional

# 评分系统配置 - 10分制
SCORING_CONFIG = {
    # 权重配置（百分比）
    "weights": {
        "initial_severity": 0.20,   # 初始严重程度权重20%
        "duration": 0.25,           # 持续时间权重25%
        "frequency": 0.20,          # 发生频率权重20%
        "business_impact": 0.25,    # 业务影响权重25%
        "service_scope": 0.10       # 影响范围权重10%
    },
    # 各项评分标准（满分10分）
    "scoring_criteria": {
        "initial_severity": {
            "warning": 3,    # 警告级: 3分
            "alert": 6,      # 警报级: 6分
            "critical": 10   # 严重级: 10分
        },
        "duration": {
            "thresholds": [30, 120, 300, 600],  # 秒 (0.5分钟, 2分钟, 5分钟, 10分钟)
            "scores": [2, 4, 6, 8, 10]          # 对应分数
        },
        "frequency": {
            "thresholds": [5, 10, 20, 50],      # 次数
            "scores": [2, 4, 6, 8, 10]          # 对应分数
        },
        "business_impact": {
            "minor": 2,      # 轻微影响: 2分
            "moderate": 5,   # 中等影响: 5分
            "major": 8,      # 重大影响: 8分
            "critical": 10   # 严重影响: 10分
        },
        "service_scope": {
            "single": 2,     # 影响1个服务: 2分
            "few": 5,        # 影响2-3个服务: 5分
            "many": 8,       # 影响4-5个服务: 8分
            "numerous": 10   # 影响5个以上服务: 10分
        }
    },
    # 严重等级阈值（10分制）
    "severity_thresholds": {
        "warning": 4.0,   # <=4.0分 为警告
        "alert": 7.0,     # 4.1-7.0分为警报
        "critical": 7.0   # >7.0分为严重
    }
}

# 核心数据结构
@dataclass
class AnomalyData:
    """
    异常数据实体类，封装异常的所有特征信息
    """
    id: str                    # 异常ID
    type: str                  # 异常类型
    measurement: str           # 监控指标大类
    field: str                 # 具体监控字段
    initial_severity: str      # 初始严重等级
    metrics: Dict[str, float]  # 指标数值
    start_time: datetime       # 首次发生时间
    duration: int              # 持续秒数
    frequency: int             # 发生次数
    business_impact: str       # 业务影响等级
    affected_services: List[str]  # 受影响服务
    device: str                # 设备标识
    tags: Dict[str, Any]       # 业务标签
    threshold: float           # 触发阈值
    current_value: float       # 当前值
    score: float = 0.0         # 综合评分（0-10）
    final_severity: str = "warning"  # 最终严重等级
    scoring_details: Dict[str, float] = None  # 各项评分详情

    def __post_init__(self):
        if self.scoring_details is None:
            self.scoring_details = {}


class ScoringSystem:
    """
    异常评分系统
    实现基于多维度评估的10分制评分机制
    """

    @staticmethod
    def calculate_item_score(item_type: str, value) -> float:
        """
        计算单项评分（满分10分）
        
        Args:
            item_type: 评分项类型
            value: 评分项的值
            
        Returns:
            float: 该评分项的得分（0-10分）
        """
        criteria = SCORING_CONFIG["scoring_criteria"][item_type]
        
        if item_type in ["initial_severity", "business_impact"]:
            # 直接映射类型
            return float(criteria.get(value, 5.0))  # 默认5分
        elif item_type == "service_scope":
            # 根据服务数量确定评分
            service_count = len(value) if isinstance(value, list) else value
            if service_count <= 1:
                return criteria["single"]
            elif service_count <= 3:
                return criteria["few"]
            elif service_count <= 5:
                return criteria["many"]
            else:
                return criteria["numerous"]
        elif item_type in ["duration", "frequency"]:
            # 阈值比较类型
            thresholds = criteria["thresholds"]
            scores = criteria["scores"]
            for i, threshold in enumerate(thresholds):
                if value <= threshold:
                    return float(scores[i])
            return float(scores[-1])  # 超过最大阈值时取最高分

    @staticmethod
    def calculate_comprehensive_score(anomaly_data: AnomalyData) -> float:
        """
        计算综合评分（满分10分）
        采用加权平均法计算最终得分
        
        Args:
            anomaly_data: 异常数据对象
            
        Returns:
            float: 综合评分（0-10分）
        """
        weights = SCORING_CONFIG["weights"]
        
        # 计算各项得分
        scores = {
            "initial_severity": ScoringSystem.calculate_item_score(
                "initial_severity", anomaly_data.initial_severity),
            "duration": ScoringSystem.calculate_item_score(
                "duration", anomaly_data.duration),
            "frequency": ScoringSystem.calculate_item_score(
                "frequency", anomaly_data.frequency),
            "business_impact": ScoringSystem.calculate_item_score(
                "business_impact", anomaly_data.business_impact),
            "service_scope": ScoringSystem.calculate_item_score(
                "service_scope", anomaly_data.affected_services)
        }
        
        # 保存各项评分详情
        anomaly_data.scoring_details = scores
        
        # 加权计算总分
        total_score = sum(
            score * weights[criteria] 
            for criteria, score in scores.items()
        )
        
        return round(total_score, 2)

    @staticmethod
    def determine_final_severity(score: float) -> str:
        """
        根据综合评分确定最终严重等级
        
        Args:
            score: 综合评分
            
        Returns:
            str: 最终严重等级（warning/alert/critical）
        """
        thresholds = SCORING_CONFIG["severity_thresholds"]
        if score <= thresholds["warning"]:
            return "warning"   # 预警
        elif score <= thresholds["alert"]:
            return "alert"     # 警报
        else:
            return "critical"  # 严重

    @staticmethod
    def evaluate_anomaly(anomaly_data: AnomalyData) -> AnomalyData:
        """
        对异常进行全面评估
        
        Args:
            anomaly_data: 异常数据对象
            
        Returns:
            AnomalyData: 评估后的异常数据对象
        """
        # 计算综合评分
        score = ScoringSystem.calculate_comprehensive_score(anomaly_data)
        anomaly_data.score = score
        
        # 确定最终严重等级
        severity = ScoringSystem.determine_final_severity(score)
        anomaly_data.final_severity = severity
        
        return anomaly_data

    @staticmethod
    def get_scoring_report(anomaly_data: AnomalyData) -> Dict[str, Any]:
        """
        生成评分报告
        
        Args:
            anomaly_data: 异常数据对象
            
        Returns:
            Dict: 评分报告
        """
        return {
            "id": anomaly_data.id,
            "综合评分": anomaly_data.score,
            "最终严重等级": anomaly_data.final_severity,
            "各项评分详情": anomaly_data.scoring_details,
            "权重配置": SCORING_CONFIG["weights"],
            "评分标准": SCORING_CONFIG["scoring_criteria"]
        }


# 业务影响评估
class BusinessImpactEvaluator:
    """
    业务影响评估器
    根据异常类型和设备确定业务影响范围
    """
    
    # 关键指标定义
    CRITICAL_METRICS = ["cpu", "mem", "disk", "net", "diskio", "system_metrics"]
    
    # 服务映射关系
    SERVICE_MAPPING = {
        "cpu": ["web", "api", "database"],
        "memory": ["web", "api", "cache"],
        "disk": ["database", "storage"],
        "diskio": ["database", "storage"],
        "network": ["web", "api", "database"],
        "system": ["general"]
    }
    
    @staticmethod
    def determine_business_impact(measurement: str, initial_severity: str) -> str:
        """
        确定业务影响等级
        
        Args:
            measurement: 监控指标类型
            initial_severity: 初始严重等级
            
        Returns:
            str: 业务影响等级
        """
        # 关键指标的严重异常具有更高业务影响
        if initial_severity == "critical" and measurement in BusinessImpactEvaluator.CRITICAL_METRICS:
            return "critical"
        elif initial_severity == "alert":
            return "moderate"
        elif initial_severity == "warning":
            return "minor"
        else:
            return "minor"
    
    @staticmethod
    def get_affected_services(measurement: str, device: str) -> List[str]:
        """
        获取受影响的服务列表
        
        Args:
            measurement: 监控指标类型
            device: 设备标识
            
        Returns:
            List[str]: 受影响的服务列表
        """
        services = BusinessImpactEvaluator.SERVICE_MAPPING.get(measurement, ["general"])
        return services


# 使用示例和测试代码
def demo_scoring_system():
    """
    演示评分系统使用方法
    """
    # 创建示例异常数据
    anomaly = AnomalyData(
        id="cpu_usage_localhost_12345",
        type="cpu_high",
        measurement="cpu",
        field="usage_idle",
        initial_severity="alert",
        metrics={"usage_idle": 20.5},
        start_time=datetime.now(timezone.utc),
        duration=150,  # 2.5分钟
        frequency=8,
        business_impact="moderate",
        affected_services=["web", "api", "database"],
        device="localhost",
        tags={"host": "server01"},
        threshold=30.0,
        current_value=20.5
    )
    
    # 评估异常
    evaluated_anomaly = ScoringSystem.evaluate_anomaly(anomaly)
    
    # 生成评分报告
    report = ScoringSystem.get_scoring_report(evaluated_anomaly)
    
    print("=== 异常评分系统演示 ===")
    print(f"异常ID: {report['id']}")
    print(f"综合评分: {report['综合评分']}")
    print(f"最终严重等级: {report['最终严重等级']}")
    print("\n各项评分详情:")
    for criterion, score in report['各项评分详情'].items():
        print(f"  {criterion}: {score}分")
    print("\n权重配置:")
    for criterion, weight in report['权重配置'].items():
        print(f"  {criterion}: {weight*100}%")


if __name__ == "__main__":
    demo_scoring_system()